#include "CaseBuilder.h"

#include "ScriptCompiler/ScriptFileContext.h"

#include "ScriptCompiler/ASTBuilder/ExpressionBuilder.h"
#include "ScriptCompiler/ASTBuilder/SentenceBlockBuilder.h"
#include "ScriptCompiler/AST/CaseNode.h"



CCaseBuilder::CCaseBuilder(
    std::shared_ptr<CScriptFileContext> InContext
    ,int32_t InEndTokenIndex
    )
{
    Context = InContext;
    Result = std::make_shared<CCaseNode>(InContext);
    EndTokenIndex = InEndTokenIndex;
}

bool CCaseBuilder::ReadCurentToken()
{
    //check 'case'
    bool bIsDefaultCase=false;
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type != EScriptTokenType::Case
            && Token->Type != EScriptTokenType::Default
        )
        {
            Context->RaiseError(10008,Token,U"Expect 'case' here");
            return false;
        }
        Result->Case = Token;
        if(Token->Type==EScriptTokenType::Default)
        {
            bIsDefaultCase=true;
        }
        Context->CurrentTokenIndex++;
    }

    if(bIsDefaultCase)
    {
        return ReadDefaultCase();
    }

    //find ':'
    uint64_t ColonIndex;
    {
        auto ColonPos=FindNextToken(EScriptTokenType::Colon,Context);
        if(!ColonPos)
        {
            //raise error, require ':'
            Context->RaiseError(10009,Context->GetCurrentToken(),U"Expect ':' after here");
            return false;
        }
        ColonIndex=*ColonPos;
    }

    //check condition
    {
        auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,ColonIndex);
        if (!ExpressionBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Condition = ExpressionBuilder->Result;
    }

    //check ':'
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type != EScriptTokenType::Colon)
        {
            Context->RaiseError(10010,Token,U"Expect ':' here");
            return false;
        }
        Context->CurrentTokenIndex++;
    }


    {
        auto SentenceBlockBuilder = std::make_shared<CSentenceBlockBuilder>(Context,EndTokenIndex);
        if (!SentenceBlockBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Body = SentenceBlockBuilder->Result;
        return true;
    }

}

bool CCaseBuilder::ReadDefaultCase()
{
    //make sure next token is ':'
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type != EScriptTokenType::Colon)
        {
            Context->RaiseError(10009,Token,U"Expect ':' after default");
            return false;
        }
        Context->CurrentTokenIndex++;
    }

    {
        auto SentenceBlockBuilder = std::make_shared<CSentenceBlockBuilder>(Context,EndTokenIndex);
        if (!SentenceBlockBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Body = SentenceBlockBuilder->Result;
        return true;
    }
}
